/*
 * This file is part of freewm.
 *
 * freewm is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * freewm is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with freewm.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "event.h"
#include "freewm.h"
#include "incs.h"
#include "wm.h"

// Start the infinite event loop and send events to handlers.
void event_loop(void)
{
	logger("Starting event loop...");
	
	XEvent ev;
	struct wm_client *c;
	
	// Infinite event loop.
	while (1)
	{
		// Get the next occurring event.
		XNextEvent(dpy, &ev);
		
		switch (ev.type)
		{
			case ButtonPress:
				logger("ButtonPress");
				module_event_exec("ButtonPress", &ev);
				break;
			case ButtonRelease:
				logger("ButtonRelease");
				module_event_exec("ButtonRelease", &ev);
				break;
			case KeyPress:
				logger("KeyPress");
				module_event_exec("KeyPress", &ev);
				break;
			case KeyRelease:
				logger("KeyRelease");
				module_event_exec("KeyRelease", &ev);
				break;
			case ConfigureRequest:
				logger("ConfigureRequest");
				module_event_exec("ConfigureRequest", &ev);
				break;
			case CirculateRequest:
				logger("CirculateRequest");
				module_event_exec("CirculateRequest", &ev);
				break;
			case MapRequest:
				logger("MapRequest");
				// Check that this isn't already one of our windows.
				// If it's not, reparent the sucker.
				if (wm_find(ev.xmaprequest.window) == NULL)
					wm_new(ev.xmaprequest.window);
					
				module_event_exec("MapRequest", &ev);
				break;
			case UnmapNotify:
				logger("UnmapNotify");
				
				// Check if this was one of our windows.
				if ((c = wm_find(ev.xunmap.window)) != NULL)
				{
					if (c->ignore_unmap)
						c->ignore_unmap = 0;
					
					// Delete the window unless we are supposed to
					// ignore unmaps on it. (This would probably be
					// if a module set the flag for an iconification
					// state)
					if (!c->ignore_unmap)
						wm_del(c, WM_DEL_UNPARENT);
				}
				
				module_event_exec("UnmapNotify", &ev);
				break;
			case DestroyNotify:
				logger("DestroyNotify");
				
				// We want to delete any of our windows that get
				// destroyed.
				if ((c = wm_find(ev.xdestroywindow.window)) != NULL)
					wm_del(c, WM_DEL_NORMAL);
					
				module_event_exec("DestroyNotify", &ev);
				break;
			case ClientMessage:
				logger("ClientMessage");
				module_event_exec("ClientMessage", &ev);
				break;
			case ColormapNotify:
				logger("ColormapNotify");
				module_event_exec("ColormapNotify", &ev);
				break;
			case PropertyNotify:
				logger("PropertyNotify");
				module_event_exec("PropertyNotify", &ev);
				break;
			case EnterNotify:
				logger("EnterNotify");
				module_event_exec("EnterNotify", &ev);
				break;
			case Expose:
				logger("Expose");
				module_event_exec("Expose", &ev);
				break;
		}
	}
}

// Perform all actions needed to start receiving events.
void event_start(void)
{
	logger("Starting event listener...");
	logger("Set window attributes of root window...");
	
	// Set which events we would like to receive from X.
	XSetWindowAttributes sattr;
	sattr.event_mask = StructMask|ButtonMask|KeyMask|ColormapChangeMask;
	
    XChangeWindowAttributes(dpy, root,
							CWEventMask, &sattr);
	
	// Look for premapped windows.
	wm_scan_premapped();
}
